home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 03 - 1987 / 03.09 Sep 87 / bit map source / bMapEdit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-06-06  |  8.8 KB  |  371 lines  |  [TEXT/KAHL]

  1. #include    <abc.h>
  2.  
  3. #include    <MacTypes.h>
  4. #include    <QuickDraw.h>
  5. #include    <EventMgr.h>
  6. #include    <WindowMgr.h>
  7. #include    <DialogMgr.h>
  8. #include    <MemoryMgr.h>
  9. #include    <ResourceMgr.h>
  10. #include    <StdFilePkg.h>
  11. #include    <FileMgr.h>
  12.  
  13. Ptr            getMap();
  14.  
  15. #define        PixelWidth    4
  16. #define        PixelHeight    4
  17.  
  18. WindowRecord    wRecord;
  19. WindowPtr        theWindow;
  20. EventRecord        theEvent;
  21.  
  22. short            nRows,
  23.                 nCols;
  24. char            theString[256];
  25.  
  26. char            *hexDigits = "0123456789ABCDEF",
  27.                 *string1 = "\Ptype BMAP=GNRL\r,128\r",
  28.                 *string2 = "\P.I ;; nRows…\r",
  29.                 *string3 = "\P.I ;; nCols…\r",
  30.                 *string4 = "\P\r",
  31.                 *string5 = "\P.H ;; the BitMap data itself…\r";
  32.  
  33. main()
  34. {
  35.     Ptr        theData;
  36.  
  37.     initialize();
  38.     theData = getMap();
  39.     if ( theData NEQ NULL ) {
  40.         editMap( theData );
  41.         writeMap( theData );
  42.     }
  43. } /* main */
  44.  
  45. initialize()
  46. {
  47.     InitGraf ( &thePort );
  48.     InitFonts();
  49.     InitWindows();
  50.     InitMenus();
  51.     TEInit();
  52.     InitDialogs ( NULL );
  53.     InitCursor();
  54. } /* initialize */
  55.  
  56. /*
  57.     This routine allocates memory for the requested bitmap and intializes
  58.     it to zero.
  59. */
  60. Ptr
  61. getMap()
  62. {
  63.     register Ptr    theData;
  64.     register short    i;
  65.  
  66.     Handle    tempHandle;
  67.     Size    theMapSize;
  68.  
  69.     nRows = nCols = 32;
  70.  
  71.     tempHandle = GetResource ( 'ICON', noteIcon );
  72.     if ( tempHandle EQ NULL )
  73.         return NULL;
  74.  
  75.     DetachResource ( tempHandle );
  76.     HLock ( tempHandle );
  77.     return *tempHandle;
  78.  
  79. } /* getMap */
  80.  
  81. editMap ( theData )
  82. Ptr        theData;
  83. {
  84.     WindowPtr    wWindow;
  85.     BitMap        theBitMap;
  86.     Rect        wRect;
  87.     Boolean        done;
  88.     short        thePart;
  89.     char        theChar;
  90.  
  91.     /* Create a window in which to display the BitMap in FatBits */
  92.     SetRect ( &wRect, 50, 50, 50+nCols*PixelWidth, 50+nRows*PixelHeight );
  93.     theWindow = NewWindow ( &wRecord, &wRect, "\PBitMap Editor", TRUE,
  94.                             4, -1L, TRUE, 0L );
  95.  
  96.     /* initialize the BitMap record, using the pointer we were given */
  97.     theBitMap.baseAddr = theData;
  98.     theBitMap.rowBytes = ( ((nCols - 1) / 16) + 1) * 2;
  99.     SetRect ( &theBitMap.bounds, 0, 0, nCols, nRows );
  100.  
  101.     /* process mouse events until user dismisses window */
  102.     done = FALSE;
  103.     do {
  104.         if ( GetNextEvent ( everyEvent, &theEvent ) ) {
  105.             switch ( theEvent.what ) {
  106.             case mouseDown:
  107.                 thePart = FindWindow ( theEvent.where, &wWindow );
  108.                 if ( wWindow EQ theWindow ) {
  109.                     switch ( thePart ) {
  110.                     case inContent:
  111.                         editBits ( theWindow, &theBitMap );
  112.                         break;
  113.                     case inGoAway:
  114.                         if ( TrackGoAway ( wWindow, theEvent.where ) ) {
  115.                             HideWindow ( wWindow );
  116.                             done = TRUE;
  117.                         }
  118.                     } /* switch ( thePart ) */
  119.                 } /* if wWindow EQ theWindow */
  120.                 break;
  121.  
  122.             case keyDown:
  123.                 theChar = theEvent.message; /* note type coersion */
  124.                 switch ( theChar ) {
  125.                 case BS:
  126.                     EraseRect ( &theWindow->portRect );
  127.                     InvalRect ( &theWindow->portRect ); /* force update event */
  128.                     break;
  129.                 case RETURN:
  130.                 case ENTER:
  131.                     done = TRUE;
  132.                     break;
  133.                 default:
  134.                     SysBeep(2);
  135.                     break;
  136.                 }
  137.                 break;
  138.  
  139.             case activateEvt:
  140.                 SetPort ( theEvent.message );
  141.                 break;
  142.  
  143.             case updateEvt:
  144.                 doUpdate ( theWindow, &theBitMap );
  145.                 break;
  146.             } /* switch ( theEvent.what ) */
  147.         } /* if GetNextEvent() */
  148.     } while ( NOT done );
  149.  
  150.  
  151. } /* editMap */
  152.  
  153. doUpdate ( badWindow, theBitMap )
  154. WindowPtr    badWindow;
  155. BitMap        *theBitMap;
  156. {
  157.     register char    *theData;
  158.     register short    j, k, rowBytes;
  159.     register char    tempChar;
  160.  
  161.     short    i;
  162.     GrafPtr    savePort;
  163.     Rect    pixelRect;
  164.  
  165.     GetPort ( &savePort );
  166.     SetPort ( badWindow );
  167.  
  168.     SetRect ( &pixelRect, 1, 1, PixelWidth, PixelHeight );
  169.  
  170.     theData = theBitMap->baseAddr;
  171.     rowBytes = theBitMap->rowBytes;
  172.  
  173.     BeginUpdate ( badWindow );
  174.  
  175.         /* Draw grid dots… */
  176.         for ( k = 0; k <= nRows; k++ ) {
  177.             MoveTo ( 0, k*PixelHeight );
  178.             for ( i = nCols; i >= 0; i-- ) {
  179.                 Move ( PixelWidth, 0 );
  180.                 Line   ( 0, 0 );
  181.             }
  182.         }
  183.  
  184.         /* Fill in contents of current BitMap */
  185.         for ( j = 0; j < nRows; j++ ) {
  186.             for ( i = 0; i < rowBytes; i++ ) {
  187.                 tempChar = theData[i+j*rowBytes];
  188.                 for ( k = 0; k < 8; k++ ) {
  189.                     if ( tempChar bAND 0x80  )
  190.                         PaintRect ( &pixelRect );
  191.                     OffsetRect ( &pixelRect, PixelWidth, 0 );
  192.                     tempChar = tempChar << 1;
  193.                 } /* for (k) */
  194.             } /* for (i) */
  195.             OffsetRect ( &pixelRect, -rowBytes*8*PixelWidth, PixelHeight );
  196.         } /* for (j) */
  197.  
  198.     EndUpdate ( badWindow );
  199.  
  200. } /* doUpdate */
  201.  
  202. editBits ( bitWindow, theBitMap )
  203. WindowPtr    bitWindow;
  204. BitMap        *theBitMap;
  205. {
  206.     register char    *theData;
  207.  
  208.     GrafPtr        myPort;
  209.     short        theError;
  210.     Point        mouseLoc;
  211.     Rect        pixelRect;
  212.     short        vHit, hHit,
  213.                 dh, dv,
  214.                 BorW;
  215.     Boolean        done;
  216.  
  217.     /* rectangle for drawing "Fat" pixel… */
  218.     SetRect ( &pixelRect, 1, 1, PixelWidth, PixelHeight );
  219.  
  220.     /* make a register copy of theBitMap->baseAddr */
  221.     theData = theBitMap->baseAddr;
  222.  
  223.     /* get memory for the GrafPort */
  224.     myPort = (GrafPtr) NewPtr ( SIZEOF(GrafPort) );
  225.     if ( MemError() ) { SysBeep(2); return; }
  226.  
  227.     /* Initialize "myPort" and install "theBitMap" */
  228.     OpenPort ( myPort );
  229.     SetPort  ( myPort ); /* Is this necessary? */
  230.     SetPortBits ( theBitMap );
  231.  
  232.     /*
  233.         First, the mouse location is recorded and tested.  If it is in the active
  234.         area, drawing begins, otherwise, we return.
  235.     */
  236.     SetPort ( bitWindow );
  237.  
  238.     GetMouse ( &mouseLoc );
  239.     dh = ( hHit = ( mouseLoc.h )/PixelWidth ) * PixelWidth;
  240.     dv = ( vHit = ( mouseLoc.v )/PixelHeight ) * PixelHeight;
  241.     if ( vHit < 0 OR vHit >= nRows OR hHit < 0 OR hHit >= nCols ) {
  242.         ClosePort ( myPort );
  243.         DisposPtr ( myPort );
  244.         SysBeep(2);
  245.         return; /* mouseDown was not in active area */
  246.     }
  247.     SetPort ( myPort );
  248.     BorW = GetPixel ( hHit, vHit ) ? patBic : patCopy;
  249.     PenMode ( BorW );
  250.     SetPort ( bitWindow );
  251.     PenMode ( BorW );
  252.  
  253.     /* The drawing begins... */
  254.     done = FALSE;
  255.     do {
  256.         if ( NOT Button() )
  257.             done = TRUE;
  258.         else {
  259.             GetMouse ( &mouseLoc );
  260.             dv = ( vHit = ( mouseLoc.v )/PixelHeight ) * PixelHeight;
  261.             dh = ( hHit = ( mouseLoc.h )/PixelWidth ) * PixelWidth;
  262.             if ( vHit < 0 OR vHit >= nRows OR hHit < 0 OR hHit >= nCols )
  263.                 ;
  264.             else  /* the mouse is in the drawing area… */{
  265.                 SetPort ( myPort );
  266.                 /* Does the hit bit need to be modified?  */
  267.                 if ( BorW EQ (GetPixel(hHit,vHit)?patBic:patCopy) ) {
  268.                     /* First, modify the "theData" through "myPort" */
  269.                     MoveTo ( hHit, vHit ); Line ( 0, 0 );
  270.                     /* Then modify the (visible) window */
  271.                     SetPort ( bitWindow );
  272.                     OffsetRect ( &pixelRect, dh, dv);
  273.                     PaintRect ( &pixelRect );
  274.                     OffsetRect ( &pixelRect, -dh, -dv);
  275.                 } else
  276.                     SetPort ( bitWindow ); /* For the next time through the loop */
  277.             }
  278.         }
  279.     } while ( NOT done );
  280.  
  281.     SetPort ( bitWindow );
  282.     PenMode ( patCopy );
  283.  
  284.     ClosePort ( myPort );
  285.     DisposPtr ( myPort );
  286.  
  287. } /* editBits */
  288.  
  289. /*
  290.     This routine writes out the contents of the bitMap in hexadecimal
  291.     in a format which RMaker will take.
  292. */
  293. writeMap ( theData )
  294. register unsigned char    *theData;
  295. {
  296.     register    i, j, rowBytes;
  297.  
  298.     SFReply        theReply;
  299.     short        theErr,
  300.                 fPathNum;
  301.     long        writeSize;
  302.     unsigned char    theChar,
  303.                     oneWord[2];
  304.  
  305.     SFPutFile ( 0x00640064,"\PSave Data File As…","\PUntitled",
  306.         NULL,&theReply);
  307.     if ( NOT theReply.good )
  308.         return;
  309.  
  310.     if ( theErr = FSOpen ( theReply.fName, theReply.vRefNum, &fPathNum ) ) {
  311.         if ( theErr NEQ fnfErr )
  312.             return;
  313.         if ( theErr = Create ( theReply.fName, theReply.vRefNum, 'BmEd', 'TEXT' ) )
  314.             return;
  315.         if ( theErr = FSOpen ( theReply.fName, theReply.vRefNum, &fPathNum ) )
  316.             return;
  317.  
  318.     }
  319.     if ( theErr = SetEOF ( fPathNum, 0L ) )
  320.         return;
  321.     if ( theErr = SetFPos ( fPathNum, fsFromStart, 0L ) ) goto err;
  322.  
  323.     /* write type and ID number… */
  324.     writeSize = string1[0];
  325.     if ( theErr = FSWrite ( fPathNum, &writeSize, string1+1 ) ) goto err;
  326.  
  327.     /* write number of rows… */
  328.     writeSize = string2[0];
  329.     if ( theErr = FSWrite ( fPathNum, &writeSize, string2+1 ) ) goto err;
  330.     NumToString ( (long) nRows, theString );
  331.     writeSize = theString[0];
  332.     if ( theErr = FSWrite ( fPathNum, &writeSize, theString+1 ) ) goto err;
  333.     writeSize = string4[0];
  334.     if ( theErr = FSWrite ( fPathNum, &writeSize, string4+1 ) ) goto err;
  335.  
  336.     /* write number of cols… */
  337.     writeSize = string3[0];
  338.     if ( theErr = FSWrite ( fPathNum, &writeSize, string3+1 ) ) goto err;
  339.     NumToString ( (long) nCols, theString );
  340.     writeSize = theString[0];
  341.     if ( theErr = FSWrite ( fPathNum, &writeSize, theString+1 ) ) goto err;
  342.     writeSize = string4[0];
  343.     if ( theErr = FSWrite ( fPathNum, &writeSize, string4+1 ) ) goto err;
  344.  
  345.     rowBytes = ( ( nCols - 1 ) / 16 + 1 ) * 2;
  346.     writeSize = string5[0];
  347.     if ( theErr = FSWrite ( fPathNum, &writeSize, string5+1 ) ) goto err;
  348.     for ( i = 0; i < nRows; i++ ) {
  349.         writeSize = 2;
  350.         for ( j = 0; j < rowBytes; j++ ) {
  351.             theChar = theData[i*rowBytes+j];
  352.             oneWord[1] = hexDigits [ theChar bAND 0x0F ];
  353.             oneWord[0] = hexDigits [ theChar >> 4 ];
  354.             if ( theErr = FSWrite ( fPathNum, &writeSize, oneWord ) ) goto err;
  355.         }
  356.         writeSize = string4[0];
  357.         if ( theErr = FSWrite ( fPathNum, &writeSize, string4+1 ) ) goto err;
  358.     }
  359.     writeSize = string4[0];
  360.     if ( theErr = FSWrite ( fPathNum, &writeSize, string4+1 ) ) goto err;
  361.  
  362.     /*
  363.         I hate goto's but this seemed the slickest way to do what I wanted
  364.         with minimal effort.
  365.     */
  366.     err: /* close the file and return */
  367.     FSClose ( fPathNum );
  368.     return;
  369.  
  370. } /* writeMap */
  371.